package com.totoro.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.totoro.exception.BusinessRuntimeException;
import com.totoro.exception.ResultCode;
import com.totoro.pojo.*;
import com.totoro.service.*;
import com.totoro.utils.ToolSecurityPwd;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author TOTORO
 * @date 2021/7/19 10:07
 * 订单Controller
 */
@Controller
@RequestMapping("/order_logic")
public class OrderController {

    @Autowired
    OrderService orderService;
    @Autowired
    ProductService productService;
    @Autowired
    ShopCouponService shopCouponService;
    @Autowired
    ShopService shopService;
    @Autowired
    CartService cartService;
    @Autowired
    SellerService sellerService;
    @Autowired
    EvaluationService evaluationService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    UserService userService;
    private static Integer count = 3;


    /**
     * 购买之前，先保存商品信息
     * @param data
     * @param session
     * @return
     */
    @SneakyThrows
    @RequestMapping(value = "/saveProductInfo", method = RequestMethod.POST)
    @ResponseBody
    public String saveProductInfo(@RequestParam("data") String data, HttpSession session){
        // 订单思路：每笔订单可能会有多个店铺，店铺里又对应了多个商品，商品又对应多个优惠券，库存，sku属性组等等。。
        // 1、但是店铺是在顶层，所有需要通过店铺作为第一层循环
        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = mapper.readTree(data);
        List<Shop> pays = new ArrayList<>();
        // 从Json获取值
        for (int i = 0; i < root.size(); i++) {
            // 第一层，获取店铺
            pays.add(shopService.findShopBySid(root.get(i).path("sid").asInt()));
            // 第二层，循环购物车的产品
            List<Product> products = new ArrayList<>();
            JsonNode pids = root.get(i).path("pids");
            JsonNode stocks = root.get(i).path("stocks");
            JsonNode skuIds = root.get(i).path("skuIds");
            for (int j = 0; j < pids.size(); j++) {
                Product product = productService.findProductById(pids.get(j).asInt());
                product.setProductCount(stocks.get(j).asInt());
                ProductSpecs productSpecs = productService.findAssignSkuByPidAndSkuId(skuIds.get(j).asInt());
                product.setProductSpecs(productSpecs);
                products.add(product);
            }
            pays.get(i).setProducts(products);
            for (Shop shop:pays) {
                System.out.println(shop);
            }
        }
        session.setAttribute("pays", pays);
        session.setMaxInactiveInterval(60*10);
        return "save success";
    }

    /**
     * 生成订单
     * @param json
     * @return
     */
    @SneakyThrows
    @RequestMapping(value = "/orderGenerate", method = RequestMethod.POST)
    @ResponseBody
    public String generateOrder(@RequestParam("jsonParam") String json, @RequestParam(value = "buyerMessages[]") String[] buyerMessage, HttpSession session){
        // 判断保存的结算商品信息是否已经过期
        List<Shop> pays = (List<Shop>) session.getAttribute("pays");
        if(null == pays || pays.size()<1){
            return "time_out_10_min";
        }
        // 获取是直接结账还是购物车结账方式
        boolean isCart = (boolean) session.getAttribute("isCart");
        User user = (User) session.getAttribute("user");

        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = mapper.readTree(json);
        List<MarketOrder> marketOrderList = new ArrayList<>();
        // 获取所有订单的总价
        double allPrice = 0.0;
        // 获取所有订单id
        Integer[] orderIds = new Integer[root.size()];
        for (int i = 0; i < root.size(); i++) {
            // 先增加订单主表
            MarketOrder marketOrder = orderService.generateOrdersPojo(user.getUserId(), root.get(i).path("sid").asInt(), root.get(i).path("arid").asInt(), 1);
            marketOrder.setBuyerMessage(buyerMessage[i]);
            // 先计算当前订单总价格 （确保添加的订单主表id从mybatis中生成策略到入参函数marketOrder中）
            double mOPrice = 0.0;
            for (int j = 0; j < root.get(i).path("pids").size(); j++) {
                ProductSpecs productSpecs =  productService.findAssignSkuByPidAndSkuId(root.get(i).path("skuIds").get(j).asInt());
                DecimalFormat df = new DecimalFormat("#.00");
                double unitPrice = Double.parseDouble(df.format(productSpecs.getProductPrice() * root.get(i).path("counts").get(j).asInt()));
                // 判断用户在该订单中是否使用了优惠券
                int couponId = root.get(i).path("couponId").asInt();
                if(couponId!=0 && j==0){
                    ShopCoupon shopCoupon = shopCouponService.findCouponByCouponId(couponId);
                    unitPrice-=shopCoupon.getCouponMoney();
                }
                mOPrice+=unitPrice;
            }
            marketOrderList.add(marketOrder);
            marketOrderList.get(i).setMarketSrOrderList(new ArrayList<MarketSrOrder>());

            allPrice+=mOPrice;
            marketOrder.setAllPrice(mOPrice);
            // 添加主訂單
            orderService.addMarketOrder(marketOrder);
            orderIds[i] = marketOrder.getId();
            // 增加一条订单的时间轴
            OrderTimeline orderTimeline = new OrderTimeline(0, marketOrder.getId(), 1);
            orderService.addOrderTimeLineByMid(orderTimeline);

            // 然后再继续订单详情表
            for (int j = 0; j < root.get(i).path("pids").size(); j++) {
                // 增加订单详情表
                MarketSrOrder marketSrOrder = new MarketSrOrder();
                marketSrOrder.setMid(marketOrder.getId());
                int pid = root.get(i).path("pids").get(j).asInt();
                marketSrOrder.setPid(pid);
                // 获得sku属性组实体对象，findAssignSkuByPidAndSkuId
                ProductSpecs productSpecs =  productService.findAssignSkuByPidAndSkuId(root.get(i).path("skuIds").get(j).asInt());
                marketSrOrder.setSkuCode(productSpecs.getId());
                // 计算单价，总价
                int count = root.get(i).path("counts").get(j).asInt();
                marketSrOrder.setBuyCount(count);
                DecimalFormat df = new DecimalFormat("#.00");
                double unitPrice = Double.parseDouble(df.format(productSpecs.getProductPrice() * count));
                // 判断用户在该订单中是否使用了优惠券
                int couponId = root.get(i).path("couponId").asInt();
                if(couponId!=0 && j==0){
                    ShopCoupon shopCoupon = shopCouponService.findCouponByCouponId(couponId);
                    unitPrice-=shopCoupon.getCouponMoney();
                    marketSrOrder.setIsUseCoupon(1);
                    marketSrOrder.setCouponId(shopCoupon.getId());
                }
                marketSrOrder.setPayPrice(unitPrice);
                marketOrderList.get(i).getMarketSrOrderList().add(marketSrOrder);
                orderService.addMarketSrOrder(marketSrOrder);
                // 如果是购物车结账，那么生成订单的时候，要删除购物车对应的记录
                if(isCart){
                    cartService.deleteCartProductBySkuIdAndPidAndUid(user.getUserId(), pid, productSpecs.getId());
                }
                // 如果是拍下立減，則此刻减少商品库存
                Product product = productService.findProductById(pid);
                if(product.getItMethod() == 0){
                    // 减库存
                    productService.updateProductStock(1, count, pid);
                    productService.updateSkuGroupStock(1, count, productSpecs.getId());
                }
            }
        }

        // 保存订单的消息提示，同时用来判断订单是否失效
        int pLen = root.get(0).path("pids").size();
        Product product = productService.findProductById(root.get(0).path("pids").get(0).asInt());
        int slid = shopService.findShopBySid(root.get(0).path("sid").asInt()).getSlid();
        User user1 = sellerService.findUserBySlid(slid);
        String msg = null;
        session.setMaxInactiveInterval(15*60);
        // 直接无视
        if(isCart) {
            if(root.size()<=1){
                if(pLen<=1){
                    msg = "天猫 -" + product.getProductName();
                } else{
                    msg = "天猫 -" + product.getProductName() + "等多件";
                }
            } else {
                msg = "合并 | " + root.size() + "笔订单";
            }
        } else{
            msg = "天猫 -" + product.getProductName();
        }
        PayDetails payDetails = new PayDetails(msg, orderIds, allPrice, System.currentTimeMillis(), user1.getUserName());
        session.setAttribute("payDetails", payDetails);
        session.setAttribute("orders", marketOrderList);
        return payDetails.getTimeStamp()+"";
    }

    /**
     * 确认付款
     * @param payPassword
     * @param payType
     * @param session
     * @param model
     * @return
     */
    @SneakyThrows
    @RequestMapping(value = "/payment", method = RequestMethod.POST)
    public String payment(@RequestParam("payPassword") String payPassword, @RequestParam("apiCode") String payType,
                          @RequestParam(value = "bizOrderId", required = false, defaultValue = "") String bizOrderId, HttpSession session, Model model){
        User sessionUser = (User) session.getAttribute("user");
        List<MarketOrder> orders = new ArrayList<>();
        // 判断是填写订单号
        if(bizOrderId.length() > 0){
            orders = orderService.findAllOrder(bizOrderId, 2, 1);
            if(orders.size() < 1){
                return "redirect:/order/confirmOrderError.htm?errorType=TIME_OUT_10_MIN";
            }
        } else {
            orders = (List<MarketOrder>) session.getAttribute("orders");
            if (null == orders || orders.size() < 1) {
                return "redirect:/order/confirmOrderError.htm?errorType=TIME_OUT_10_MIN";
            }
        }

        User user = userService.findUser(sessionUser.getUserId());
        // 如果支付密码解密正确
        boolean isScd = ToolSecurityPwd.authenticate(payPassword, user.getPayPassword(), user.getPaySalt());
        if(isScd){
            // 将订单的支付类型修改
            for (MarketOrder order:orders) {
                order.setOrderStatus(2);
                order.setPayType(payType);
                order.setPayTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                orderService.updateOrder(order);
                OrderTimeline orderTimeline = new OrderTimeline(0, order.getId(), 2);
                orderService.addOrderTimeLineByMid(orderTimeline);
            }
            // 获得订单下的所有商品，添加一条购买过的记录 & 添加店铺支付金额
            for (MarketOrder order : orders) {
                shopService.addShopPay(order.getSid(), order.getAllPrice());
                for (MarketSrOrder marketSrOrder : order.getMarketSrOrderList()) {
                    int cid = productService.findCategoryIdByPid(marketSrOrder.getPid());
                    // 增加一次该类别的次数根据 cid
                    categoryService.updateBuyCounyByCid(cid);
                    // 增加自己的信誉分2分
                    userService.addUserScore(user.getUserId(), 2);
                    // 判断该商品是否为付款减库存，如果是，则减去
                    Product product = productService.findProductById(marketSrOrder.getPid());
                    if(product.getItMethod() == 1){
                        // 减库存
                        productService.updateProductStock(1, marketSrOrder.getBuyCount(), product.getId());
                        productService.updateSkuGroupStock(1, marketSrOrder.getBuyCount(), marketSrOrder.getSkuCode());
                    }
                    // 添加购买过的记录
                    BuyShop buyShop = new BuyShop(user.getUserId(), order.getSid(), marketSrOrder.getPid());
                    BuyShop checkBuyShop = productService.checkUserBuyShop(buyShop);
                    if(null == checkBuyShop) {
                        productService.addBuyShop(buyShop);
                    }
                }
            }
            // 减库存

            Thread.sleep(1000);
            return "redirect:/order/paySuccess.htm";
        } else{
            count--;
            if(count == 0){
                session.removeAttribute("user");
                session.removeAttribute("orders");
                session.removeAttribute("pays");
                count = 3;
                Thread.sleep(1000);
                return "redirect:/login.htm";
            }
            session.setAttribute("errorMsg","密码输入错误，你还有"+count+"次机会重新输入");
            session.setMaxInactiveInterval(10);
            PayDetails payDetails = (PayDetails) session.getAttribute("payDetails");
            return "redirect:/order/lightPayCashier.htm?timeStamp="+payDetails.getTimeStamp();
        }
    }

    /**
     * 修改订单状态，添加时间轴
     * @param orderId
     * @param status
     * @return
     */
    @RequestMapping(value = "/updateOrderStatus", method = RequestMethod.POST)
    @ResponseBody
    public String updateOrderStatus(@RequestParam("bizOrderId") String orderId, @RequestParam("status") Integer status){
        // 1、修改订单状态， 2、创建该订单的状态变化时间轴
        MarketOrder marketOrder = orderService.findMarketOrderByMarketOdd(orderId);
        marketOrder.setOrderStatus(status);
        orderService.updateOrder(marketOrder);
        orderService.addOrderTimeLineByMid(new OrderTimeline(0, marketOrder.getId(), status));
        return "success";
    }

    /**
     * 批量修改状态
     * @param orderIds
     * @param status
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/batchUpdateOrderStatus", method = RequestMethod.POST)
    public String batchUpdateOrderStatus(@RequestParam("bizOrderIds[]") String[] orderIds, @RequestParam("status") Integer status ){
        for (int i = 0; i < orderIds.length; i++) {
            // 1、修改订单状态， 2、创建该订单的状态变化时间轴
            MarketOrder marketOrder = orderService.findMarketOrderByMarketOdd(orderIds[i]);
            marketOrder.setOrderStatus(status);
            orderService.updateOrder(marketOrder);
            orderService.addOrderTimeLineByMid(new OrderTimeline(0, marketOrder.getId(), status));
        }
        return "success";
    }

    /**
     * 修改详情订单价格
     * @param srId
     * @param price
     * @return
     */
    @RequestMapping("/updateSrOrderPayPrice")
    @ResponseBody
    public String updateSrOrderPayPrice(@RequestParam("srId") int srId, @RequestParam("payPrice") double price){
        // 计算这次的价格与上一次的价格相差多少
        MarketSrOrder marketSrOrder = orderService.findMarketSrOrderByMsroId(srId);
        double finalAllPrice = price - marketSrOrder.getPayPrice();
        // 修改主表价格
        MarketOrder marketOrder = orderService.findMarketByMarketSrOrderId(srId);
        orderService.updateOrderAllPrice(marketOrder.getId(), marketOrder.getAllPrice()+finalAllPrice);
        // 修改详情价格
        orderService.updateSrOrderPayPrice(srId, price);
        return "success";
    }

    /**
     * 将一个订单逻辑删除至订单回收站
     * @param moId
     * @return
     */
    @RequestMapping("/falseDeleteOrder")
    @ResponseBody
    public String falseDeleteOrder(@RequestParam("moId") int moId){
        orderService.falseDeleteOrder(moId);
        return "success";
    }

    /**
     * 订单删除 - 批量修改真的删除状态
     * @param moIds
     * @return
     */
    @RequestMapping("/batchTrueDeleteOrder")
    @ResponseBody
    public String batchTrueDeleteOrder(@RequestParam("moIds[]") int[] moIds){
        orderService.trueDeleteOrder(moIds);
        return "success";
    }

    /**
     * 批量还原订单
     * @param moIds
     * @return
     */
    @RequestMapping("/batchReductionOrder")
    @ResponseBody
    public String batchReductionOrder(@RequestParam("moIds[]") int[] moIds){
        orderService.reductionOrder(moIds);
        return "success";
    };


    /**
     * 确认收货
     * @param orderId
     * @param payPassword
     * @param model
     * @param session
     * @return
     * @throws ParseException
     */
    @SneakyThrows
    @RequestMapping(value = "/confirmReceipt", method = RequestMethod.POST)
    public String confirmReceipt(@RequestParam("bizOrderId") String orderId, @RequestParam("payPassword") String payPassword, Model model, HttpSession session) throws ParseException {
        MarketOrder marketOrderFlag = orderService.findMarketOrderByMarketOdd(orderId);
        if(marketOrderFlag.getOrderStatus()!=3){
            return "redirect:/order/confirmOrderError.htm?errorType=ALREADY_RECEIPT";
        }
        User user = (User) session.getAttribute("user");
        // 比对支付密码 ， 先解密支付密码
        boolean isScd = ToolSecurityPwd.authenticate(payPassword, user.getPayPassword(), user.getPaySalt());
        if(isScd) {
            // 我已收货，增加本次所有商品的成交次数
            MarketOrder marketOrder = orderService.findAllOrder(orderId, 2, 0).get(0);
            for (MarketSrOrder marketSrOrder : marketOrder.getMarketSrOrderList()) {
                productService.updateProductDealCountByPid(marketSrOrder.getProduct().getId());
                productService.updateProductMonthDeal(new ProductMonthDeal(marketSrOrder.getProduct().getId()));
            }
            // 改变为已收货，增加收货时间轴
            marketOrder.setOrderStatus(4);
            orderService.updateOrder(marketOrder);
            OrderTimeline orderTimeline = new OrderTimeline(0, marketOrder.getId(), 4);
            orderService.addOrderTimeLineByMid(orderTimeline);
            long timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(marketOrder.getCreateTime()).getTime();
            return "redirect:/order/transaction_success.htm?bizOrderId="+orderId+"&timeStamp="+timeStamp;
        } else{
            count--;
            if(count == 0){
                session.removeAttribute("user");
                count = 3;
                Thread.sleep(1000);
                return "redirect:/login.htm";
            }
            session.setAttribute("errorMsg","密码输入错误，你还有"+count+"次机会重新输入");
            session.setMaxInactiveInterval(10);
            return "redirect:/order/confirm_goods.htm?bizOrderId="+orderId;
        }
    }


    /**
     * 比较支付密码
     * @param payPassword
     * @param session
     * @return
     */
    @RequestMapping(value = "/quitePayPassword", method = RequestMethod.POST)
    @ResponseBody
    public String quitePayPassword(@RequestParam("payPassword") String payPassword, HttpSession session){
        User user = (User) session.getAttribute("user");
        if(null == user){
            return "fail";
        }
        // 比对支付密码 ， 先解密支付密码
        boolean isScd = ToolSecurityPwd.authenticate(payPassword, user.getPayPassword(), user.getPaySalt());
        if(isScd){
            return "success";
        }
        return "fail";
    }

    /**
     * 批量确认收货，直接刷新页面
     * @param bizOrderIds
     * @return
     */
    @RequestMapping(value = "/batch_confirm_goods", method = RequestMethod.POST)
    @ResponseBody
    public String batchConfirmGoods(@RequestParam("bizOrderIds[]") String[] bizOrderIds){
        for (int i = 0; i < bizOrderIds.length; i++) {
            MarketOrder marketOrder = orderService.findAllOrder(bizOrderIds[i], 2, 0).get(0);
            // 增加商品成交数
            for (MarketSrOrder marketSrOrder : marketOrder.getMarketSrOrderList()) {
                productService.updateProductMonthDeal(new ProductMonthDeal(marketSrOrder.getProduct().getId()));
                productService.updateProductDealCountByPid(marketSrOrder.getProduct().getId());
            }
            // 改变为已收货，增加收货时间轴
            marketOrder.setOrderStatus(4);
            orderService.updateOrder(marketOrder);
            OrderTimeline orderTimeline = new OrderTimeline(0, marketOrder.getId(), 4);
            orderService.addOrderTimeLineByMid(orderTimeline);
        }
        return "success";
    }


    /**
     * 确认评论
     * @param productComment
     * @param files
     * @param request
     * @param session
     * @return
     */
    @SneakyThrows
    @RequestMapping(value = "/confirmRate", method = RequestMethod.POST)
    public String confirmRate(ProductComment productComment, @RequestParam("eImages") MultipartFile[] files, HttpServletRequest request,
                              HttpSession session){
        // 獲得該次訂單詳表記錄，如果這個詳情訂單已經被客戶評價過，則不允許繼續操作
        MarketSrOrder mas = orderService.findMarketSrOrderByMsroId(productComment.getMsId());
        if(mas.getIsComment() == 1){
            String configCode= URLEncoder.encode("该订单已经评论过了","UTF-8");
            return "redirect:/tmall_process_error.htm?errorType=ALREADY_APPEND_RATE&errorMsg="+configCode;
        }

        User user = (User) session.getAttribute("user");
        productComment.setUid(user.getUserId());
        if(files.length >=1) {
            productComment.setIsHaveImage(1);
        }
        System.out.println(productComment);
        // 将主评论添加至数据库
        evaluationService.addProductComment(productComment);
        // 将该商品评论次数+1
        MarketSrOrder mso = orderService.findMarketSrOrderByMsroId(productComment.getMsId());
        System.out.println(mso.getPid()+"的哇哦看到我扩大我开大我都快哇哦扩大为");
        productService.addProductCommentCount(mso.getPid());
        // 如果用户上传了图片
        if(files.length >=1) {
            // 添加评论图片
            evaluationService.addProductCommentImage(productComment.getId(), files, request);
            // 设置是否有图片字段为1
        }
        // 修改详情订单的评价状态，已评价
        orderService.updateMarketSrOrderCommentStatus(productComment.getMsId());

        // 获得主订单id
        String orderId = orderService.findMarketByMarketSrOrderId(productComment.getMsId()).getMarketOdd();
        MarketOrder marketOrder = orderService.findAllOrder(orderId, 2, 0).get(0);
        // 添加时间轴，修改订单状态
        // 1、如果订单下的所有详情订单都评论过了，则修改状态
        boolean isAll = true;
        for (MarketSrOrder marketSrOrder : marketOrder.getMarketSrOrderList()) {
            if(marketSrOrder.getIsComment() == 0){
                isAll = false;
            }
        }
        // 如果详情订单都评价过了
        if(isAll){
            marketOrder.setOrderStatus(5);
            orderService.updateOrder(marketOrder);
            OrderTimeline orderTimeline = new OrderTimeline(0, marketOrder.getId(), 5);
            orderService.addOrderTimeLineByMid(orderTimeline);
        }
        // 修改卖家的积分，店铺的积分
        shopService.updateShopStar(productComment);
        sellerService.updateSellerScore(productComment.getCommentScore(), productComment.getSlid());
        Shop shop = shopService.findShopBySlid(productComment.getSlid());
        return "redirect:/order/remarkSeller4Mall.htm?brandID="+shop.getId();
    }

    /**
     * 确认追评
     * @param appendComment
     * @param msId
     * @param pid
     * @param files
     * @param request
     * @param session
     * @return
     */
    @SneakyThrows
    @RequestMapping(value = "/confirmAppendRate", method = RequestMethod.POST)
    public String confirmAppendRate(AppendComment appendComment, @RequestParam("msId") Integer msId, @RequestParam("pid") Integer pid,
                                    @RequestParam("eImages") MultipartFile[] files, HttpServletRequest request, HttpSession session){
        System.out.println(appendComment);
        User user = (User) session.getAttribute("user");
        if(user == null){
            return "redirect:/login.htm";
        }
        // 如果该订单的人和评论的人并不一样
        MarketOrder marketOrder = orderService.findMarketByMarketSrOrderId(msId);
        if(user.getUserId() != marketOrder.getUid()){
            return "redirect:/login.htm";
        }
        // 如果用户选择了图片
        if(files.length > 0){
            appendComment.setIsHaveImage(1);
        }
        // 添加追评
        evaluationService.addProductAppendComment(appendComment);
        // 修改该订单为已追评
        orderService.updateMarketSrOrderAppendCommentStatus(msId);
        if(files.length > 0){
            evaluationService.addProductAppendCommentImage(appendComment.getId(), files, request);
        }
        Thread.sleep(1000);
        return "redirect:/buy.htm?pid="+pid+"&skuCode=0";
    }

}
